
#include <QtGui>
#include <vector>
#include <string>
#include "Matrix.h"
#include "SpreadSheet.h"
#include "Helper.h"

CSpreadsheet::CSpreadsheet(QWidget *pParent_)
    : QTableWidget(pParent_)
{
    _pAct = new QAction(this);
    _pAct->setCheckable(true);
    connect(_pAct, SIGNAL(triggered()),this, SLOT(show()));
    connect(_pAct, SIGNAL(triggered()),this, SLOT(setFocus()));
    connect(_pAct, SIGNAL(triggered()),this, SLOT(updateStatusBar()));
    //connect(this, SIGNAL(currentCellChanged(int, int, int, int)),this, SLOT(updateStatusBar()));

    _eSortOrder = Qt::AscendingOrder;
    autoRecalc = true;

    setItemPrototype(new CCell);
    setSelectionMode(ContiguousSelection);

    connect(this, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(somethingChanged()));
    setContextMenuPolicy(Qt::DefaultContextMenu);
    clear();
    updateStatusBar();
}
void CSpreadsheet::updateStatusBar()
{
    if(parentWidget()) 
        parentWidget()->setWindowModified(true);
    //qobject_cast<QMainWindow*>(parentWidget())->statusBar()->showMessage("Test",2000);
    //there is a memory conflicts when running don't know why
    //setStatusTip(QString(QFileInfo(_sCurFile).fileName()).toUpper()+":"+currentLocation());
    //above works but tips updated only when pointer moves to other sub-window
}
void CSpreadsheet::clear()
{
    setRowCount(0);
    setColumnCount(0);
    setRowCount(RowCount);
    setColumnCount(ColumnCount);

    for (int i = 0; i < ColumnCount; ++i) {
        QTableWidgetItem *item = new QTableWidgetItem;
        item->setText(QString(QChar('A' + i)));
        setHorizontalHeaderItem(i, item);
    }

    setCurrentCell(0, 0);
}

CCell *CSpreadsheet::cell(int row, int column) const
{
    return static_cast<CCell *>(item(row, column));
}

QString CSpreadsheet::text(int row, int column) const
{
    CCell *c = cell(row, column);
    if (c) {
        return c->text();
    } else {
        return "";
    }
}

QString CSpreadsheet::formula(int row, int column) const
{
    CCell *c = cell(row, column);
    if (c) {
        return c->formula();
    } else {
        return "";
    }
}

void CSpreadsheet::setFormula(int row, int column, const QString &formula)
{
    CCell *c = cell(row, column);
    if (!c) {
        c = new CCell;
        setItem(row, column, c);
    }
    c->setFormula(formula);
}

void CSpreadsheet::initPrjContent(const QStringList& lFileNames_)
{
    Q_ASSERT(lFileNames_.at(0).contains(".prj"));
    for (int row = 1; row < lFileNames_.length(); ++row) {
        setFormula(row-1,0,QFileInfo(lFileNames_.at(row)).fileName());
    }
}

QString CSpreadsheet::currentLocation() const
{
    return QChar('A' + currentColumn()) + QString::number(currentRow() + 1);
}

QString CSpreadsheet::currentFormula() const
{
    return formula(currentRow(), currentColumn());
}

void CSpreadsheet::somethingChanged()
{
    if (autoRecalc)
        recalculate();
    emit modified();
    setWindowModified(true);
}

bool CSpreadsheet::writeFile(const QString &fileName)
{
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly|QIODevice::Text)) {
        QMessageBox::warning(this, tr("Spreadsheet"),
                             tr("Cannot write file %1:\n%2.")
                             .arg(file.fileName())
                             .arg(file.errorString()));
        return false;
    }
    //QDataStream out(&file);
    //out.setVersion(QDataStream::Qt_4_3);

    //out << quint32(MagicNumber);

    //QApplication::setOverrideCursor(Qt::WaitCursor);
    //for (int row = 0; row < RowCount; ++row) {
    //    for (int column = 0; column < ColumnCount; ++column) {
    //        QString str = formula(row, column);
    //        if (!str.isEmpty()){
    //            //out << QString::number(row) << QString::number(column) << str;
    //            out << quint16(row) << quint16(column) << str;
    //            //int nRow = QString::number(row).length();
    //            //int nCol = QString::number(column).length();

    //            //out.writeRawData(QString::number(row).toStdString().c_str(),QString::number(row).length());out <<" ";
    //            //out.writeRawData(QString::number(column).toStdString().c_str(),QString::number(column).length());out<<" ";
    //            //out.writeRawData(str.toStdString().c_str(),str.length());out <<"\n";//out <<"\n";
    //        }
    //    }
    //}
    QTextStream out(&file);
    out<<MagicNumber<<endl; 
    for (int row = 0; row < RowCount; ++row) {
        for (int column = 0; column < ColumnCount; ++column) {
            QString str = formula(row, column);
            if (!str.isEmpty())
                out << row << " " << column << " " << str << endl;
        }
    }
    QApplication::restoreOverrideCursor();
    return true;
}

bool CSpreadsheet::readFile(const QString &fileName)
{
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly)) {
        QMessageBox::warning(this, tr("Spreadsheet"),
                             tr("Cannot read file %1:\n%2.")
                             .arg(file.fileName())
                             .arg(file.errorString()));
        return false;
    }

    //QDataStream in(&file);
    //in.setVersion(QDataStream::Qt_4_3);

    //quint32 magic;
    //in >> magic;
    //if (magic != MagicNumber) {
    //    QMessageBox::warning(this, tr("Spreadsheet"),
    //                         tr("The file is not a Spreadsheet file."));
    //    return false;
    //}

    //clear();

    //quint16 row;
    //quint16 column;
    //QString str;
    //QString sRow,sCol;
    //bool bOK;

    //QApplication::setOverrideCursor(Qt::WaitCursor);
    //while (!in.atEnd()) {
    //    //in >> sRow >> sCol >> str;
    //    in >> row >> column >> str;
    //    //in.readRawData(,)
    //    //setFormula(sRow.toInt(&bOK), sCol.toInt(&bOK), str);
    //    setFormula(row, column, str);
    //}
    QTextStream in(&file);
    QString line = in.readLine();
    
    if(!line.contains(QString::number(MagicNumber)))
    {
        QMessageBox::warning(this, tr("Spreadsheet"),tr("The file is not a Spreadsheet file."));
        return false;
    }
    while (!in.atEnd()) {
        QString line = in.readLine();
        QStringList fields = line.split(' ');
        if (fields.size() >= 3) {
            int row = fields.takeFirst().toInt();
            int column = fields.takeFirst().toInt();
            setFormula(row, column, fields.join(" "));
        }
    }
    QApplication::restoreOverrideCursor();
    return true;
}

void CSpreadsheet::cut()
{
    copy();
    del();
}
void CSpreadsheet::cutCurrentRow()
{
    copy();
    removeCurrentRow(); 
}
void CSpreadsheet::createFile(const QString& sPathFileNameExt_)
{
    static int nDocumentNumber = 1;
    
    _bIsUntitled = true;
    setCurrentFile(sPathFileNameExt_);
    setSubWindowIcons(sPathFileNameExt_);
    //connect(this, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(somethingChanged()));
    saveFile(sPathFileNameExt_);
    ++nDocumentNumber;
}
void CSpreadsheet::setSubWindowIcons(const QString& sPathFileNameExt_)
{
    // set window icon
    if(sPathFileNameExt_.contains(".prj"))
    {
        setWindowIcon(QIcon(":/images/project_whole.png"));
    }
    else if(sPathFileNameExt_.contains(".init"))
    {
        setWindowIcon(QIcon(":/images/init.png"));
    }
    else if(sPathFileNameExt_.contains(".spc"))
    {
        setWindowIcon(QIcon(":/images/spectral.png"));
    }
    else if(sPathFileNameExt_.contains(".scr"))
    {
        setWindowIcon(QIcon(":/images/script.png"));
    }
    else if(sPathFileNameExt_.contains(".out"))
    {
        setWindowIcon(QIcon(":/images/output.png"));
    }
    else if(sPathFileNameExt_.contains(".mtx"))
    {
        setWindowIcon(QIcon(":/images/matrix.png"));
    }
}


void CSpreadsheet::copy()
{
    QTableWidgetSelectionRange range = selectedRange();
    QString str;

    for (int i = 0; i < range.rowCount(); ++i) {
        if (i > 0)
            str += "\n";
        for (int j = 0; j < range.columnCount(); ++j) {
            if (j > 0)
                str += "\t";
            str += formula(range.topRow() + i, range.leftColumn() + j);
        }
    }
    QApplication::clipboard()->setText(str);
}

QTableWidgetSelectionRange CSpreadsheet::selectedRange() const
{
    QList<QTableWidgetSelectionRange> ranges = selectedRanges();
    if (ranges.isEmpty())
        return QTableWidgetSelectionRange();
    return ranges.first();
}

void CSpreadsheet::paste()
{
    QTableWidgetSelectionRange range = selectedRange();
    QString str = QApplication::clipboard()->text();
    QStringList rows = str.split('\n');
    int numRows = rows.count();
    int numColumns = rows.first().count('\t') + 1;

    if (range.rowCount() * range.columnCount() != 1
            && (range.rowCount() != numRows
                || range.columnCount() != numColumns)) {

        QMessageBox::information(this, tr(_sCurFile.toStdString().c_str()),
                tr("The information cannot be pasted because the copy "
                   "and paste areas aren't the same size."));
        return;
    }

    for (int i = 0; i < numRows; ++i) {
        QStringList columns = rows[i].split('\t');
        for (int j = 0; j < numColumns; ++j) {
            int row = range.topRow() + i;
            int column = range.leftColumn() + j;
            if (row < RowCount && column < ColumnCount)
                setFormula(row, column, columns[j]);
        }
    }
    somethingChanged();
}

void CSpreadsheet::del()
{
    QTableWidgetSelectionRange range = selectedRange();
    // the whole columes were selected then perform removing action
    if(range.columnCount()==columnCount())
    {
        removeCurrentRow();
    }
    else
    {
        QList<QTableWidgetItem *> items = selectedItems();
        if (!items.isEmpty()) {
            foreach (QTableWidgetItem *item, items)
                delete item;
            somethingChanged();
        }
    }
}

void CSpreadsheet::removeCurrentRow()
{
    removeRow( currentRow() );
}

void CSpreadsheet::insertRowAboveCurrent()
{
    insertRow( currentRow() );
    removeRow( rowCount()-1 );
}

void CSpreadsheet::selectCurrentRow()
{
    selectRow(currentRow());
}

void CSpreadsheet::selectCurrentColumn()
{
    selectColumn(currentColumn());
}

bool CSpreadsheet::findNext(const QString &str, Qt::CaseSensitivity cs)
{
    int row = currentRow();
    int column = currentColumn() + 1;

    while (row < RowCount) {
        while (column < ColumnCount) {
            if (text(row, column).contains(str, cs)) {
                clearSelection();
                setCurrentCell(row, column);
                activateWindow();
                return true;
            }
            ++column;
        }
        column = 0;
        ++row;
    }
    QApplication::beep();
    return false;
}

bool CSpreadsheet::findPrevious(const QString &str,Qt::CaseSensitivity cs)
{
    int row = currentRow();
    int column = currentColumn() - 1;

    while (row >= 0) {
        while (column >= 0) {
            if (text(row, column).contains(str, cs)) {
                clearSelection();
                setCurrentCell(row, column);
                activateWindow();
                return true;
            }
            --column;
        }
        column = ColumnCount - 1;
        --row;
    }
    QApplication::beep();
    return false;
}

void CSpreadsheet::recalculate()
{
    for (int row = 0; row < RowCount; ++row) {
        for (int column = 0; column < ColumnCount; ++column) {
            if (cell(row, column))
                cell(row, column)->setDirty();
        }
    }
    viewport()->update();
}

void CSpreadsheet::setAutoRecalculate(bool recalc)
{
    autoRecalc = recalc;
    if (autoRecalc)
        recalculate();
}



bool CSpreadsheetCompare::operator()(const QStringList &row1,
                                    const QStringList &row2) const
{
    for (int i = 0; i < KeyCount; ++i) {
        int column = keys[i];
        if (column != -1) {
            if (row1[column] != row2[column]) {
                if (ascending[i]) {
                    return row1[column] < row2[column];
                } else {
                    return row1[column] > row2[column];
                }
            }
        }
    }
    return false;
}

CSpreadsheet* CSpreadsheet::open(QWidget *pParent_)
{
    QString sFileName = QFileDialog::getOpenFileName(pParent_,tr("Open"),".",
        tr("(*.prj *.init *.spc *.scr *.out)\n" "project files (*.prj)\n" "init files (*.init)\n" "spectral files (*.spc)\n" "output files (*.out)\n" "All files (*.*)"));
    if(sFileName.isEmpty())
        return 0;
    return openFile(sFileName,pParent_);
}

CSpreadsheet* CSpreadsheet::openFile(const QString& sPathFileNameExt_, QWidget *pParent_, QStringList* plFileNames_/*=NULL*/)
{
    if(plFileNames_) // to acquire a list of file names 
    {
        plFileNames_->clear();
        plFileNames_->append(sPathFileNameExt_);
        CSpreadsheet *pSpreadsheet = new CSpreadsheet(pParent_);
        if(pSpreadsheet->readFile(sPathFileNameExt_))
        {
            pSpreadsheet->setCurrentFile(sPathFileNameExt_);
            if(QFileInfo(sPathFileNameExt_).fileName().contains(".prj")){
                for (int r = 0; r < RowCount; ++r) {
                    if(!pSpreadsheet->text(r,0).isEmpty())
                        plFileNames_->append(QFileInfo(sPathFileNameExt_).path()+"/"+pSpreadsheet->text(r,0));
                }
            }
        }
        delete pSpreadsheet;
        return NULL;
    }
    else 
    {
        CSpreadsheet *pSpreadsheet = new CSpreadsheet(pParent_);
        pSpreadsheet->setSubWindowIcons(sPathFileNameExt_);
        if(pSpreadsheet->readFile(sPathFileNameExt_)){
            pSpreadsheet->setCurrentFile(sPathFileNameExt_);
            if(plFileNames_&&QFileInfo(sPathFileNameExt_).fileName().contains(".prj")){
                for (int r = 0; r < RowCount; ++r) {
                    if(!pSpreadsheet->text(r,0).isEmpty())
                        plFileNames_->append(QFileInfo(sPathFileNameExt_).path()+"/"+pSpreadsheet->text(r,0));
                }
            }
            return pSpreadsheet;
        }
        else{
            delete pSpreadsheet;
            return 0;
        }
    }
}

void CSpreadsheet::setCurrentFile(const QString &sPathFileNameExt_)
{
    _sCurFile = sPathFileNameExt_;
    _bIsUntitled = false;
    _pAct->setText(QFileInfo(sPathFileNameExt_).fileName());
    //document()->setModified(false);
    setWindowModified(false);
    setWindowTitle(QFileInfo(sPathFileNameExt_).fileName()+"[*]");
    setWindowModified(false);
}

bool CSpreadsheet::save()
{
    if(_bIsUntitled)
    {
        return saveAs();
    }
    else
    {
        return saveFile(_sCurFile);
    }
}
bool CSpreadsheet::saveAs()
{
    QString sFilter;
    if(_sCurFile.contains(".prj"))
    {
        sFilter =  tr("project (*.prj)\n" "init files (*.init)\n" "script files (*.scr)\n" "spectral files (*.spc)\n" "output files (*.out)\n" "All files (*.*)");
    }
    else if(_sCurFile.contains(".init"))
    {
        sFilter =  tr("init files (*.init)\n" "project (*.prj)\n" "script files (*.scr)\n" "spectral files (*.spc)\n" "output files (*.out)\n" "All files (*.*)");
    }
    else if(_sCurFile.contains(".out"))
    {
        sFilter =  tr("output files (*.out)\n" "init files (*.init)\n" "script files (*.scr)\n" "project (*.prj)\n" "spectral files (*.sp)\n" "All files (*.*)");
    }
    else if(_sCurFile.contains(".spc"))
    {
        sFilter =  tr("spectral files (*.spc)\n" "init files (*.init)\n" "project (*.prj)\n" "script files (*.scr)\n" "output files (*.out)\n" "All files (*.*)");
    }
    else if(_sCurFile.contains(".scr"))
    {
        sFilter =  tr("script files (*.scr)\n" "spectral files (*.spc)\n" "init files (*.init)\n" "project (*.prj)\n" "output files (*.out)\n" "All files (*.*)");
    }

    QString sFileName = QFileDialog::getSaveFileName(this, tr("Save As"),_sCurFile,sFilter);
    if (sFileName.isEmpty())
        return false;

    return saveFile(sFileName);
}

bool CSpreadsheet::saveFile(const QString &sFullFileName_)
{
    writeFile(sFullFileName_);
    setCurrentFile(sFullFileName_);
    return true;
}

void CSpreadsheet::closeEvent(QCloseEvent *event)
{
    if (okToContinue()) {
        event->accept();
    } else {
        event->ignore();
    }
}

bool CSpreadsheet::okToContinue()
{
    if (isWindowModified()) {
        int r = QMessageBox::warning(this, tr(_sCurFile.toStdString().c_str()),
            tr("The document has been modified.\n"
            "Do you want to save your changes?"),
            QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
        if (r == QMessageBox::Yes) {
            return save();
        } else if (r == QMessageBox::Cancel) {
            return false;
        }
    }
    return true;
}

QString CSpreadsheet::fileType() const
{
    Q_ASSERT(!_sCurFile.isEmpty());
    if(_sCurFile.contains(".prj"))
        return ".prj";
    else if(_sCurFile.contains(".init"))
        return ".init";
    else if(_sCurFile.contains(".scr"))
        return ".scr";
    else if(_sCurFile.contains(".spc"))
        return ".spc";
    else if(_sCurFile.contains(".out"))
        return ".out";
    return "";
}
void CSpreadsheet::search(const QString& sKey_,int nNum_, string* pResult_ )
{
    Q_ASSERT(pResult_);
    pResult_->clear();
    for(int r=0;r<RowCount;r++)
    for(int c=0;c<ColumnCount;c++){
        if(cell(r,c)&&cell(r,c)->text().contains(sKey_)){
            if(cell(r,c+nNum_))
                (*pResult_) = cell(r,c+nNum_)->formula().toStdString();
            return;
        }  
    }

    {
        QString sError("you need to specify ");
        sError += sKey_;
        sError += ".\n";
        throw exception(sError.toStdString().c_str());
    }
    return;
}
void CSpreadsheet::search(const QString& sKey_,int nDim_, vector<string>* pvsResult_ )
{
    Q_ASSERT(pvsResult_);
    pvsResult_->clear();
    for(int r=0;r<RowCount;r++)
    for(int c=0;c<ColumnCount;c++){
        if(cell(r,c)&&cell(r,c)->text().contains(sKey_)){
            for(int i =0; i<nDim_;i++){
                pvsResult_->push_back(cell(r,c+1+i)->formula().toStdString());
            }
            return;
        }  
    }

    {
        QString sError("you need to specify ");
        sError += sKey_;
        sError += ".\n";
        throw exception(sError.toStdString().c_str());
    }
    return;
}


//void CSpreadsheet::search( const QString& sKey_, double* pResult_ )
//{
//    Q_ASSERT(pResult_);
//    for(int r=0;r<RowCount;r++)
//        for(int c=0;c<ColumnCount;c++){
//            if(cell(r,c)&&cell(r,c)->text().contains(sKey_)){
//                if(!cell(r,c+1)) 
//                {
//                    QString sError("the entry after \"");
//                    sError += sKey_;
//                    sError += "\" should not be empty.\n";
//                    sError += currentFile();
//                    sError += ".\n";
//                    throw exception(sError.toStdString().c_str());
//                }
//                helpers::validate(*pResult_,cell(r,c+1)->formula().toStdString());
//
//                //(*pResult_)=cell(r,c+1)->formula().toDouble();
//                return;
//            }  
//        }
//
//    {
//        QString sError("you need to specify \"");
//        sError += sKey_;
//        sError += "\".\n";
//        sError += currentFile();
//        sError += ".\n";
//        throw exception(sError.toStdString().c_str());
//    }
//    return;
//}
//
//void CSpreadsheet::search( const QString& sKey_, int* pResult_ )
//{
//    Q_ASSERT(pResult_);
//    for(int r=0;r<RowCount;r++)
//        for(int c=0;c<ColumnCount;c++){
//            if(cell(r,c)&&cell(r,c)->text().contains(sKey_)){
//                if(!cell(r,c+1)) 
//                {
//                    QString sError("the entry after \"");
//                    sError += sKey_;
//                    sError += "\" should not be empty.\n";
//                    sError += currentFile();
//                    sError += ".\n";
//                    throw exception(sError.toStdString().c_str());
//                }
//                (*pResult_)=cell(r,c+1)->formula().toInt();
//                return;
//            }  
//        }
//
//        {
//            QString sError("you need to specify \"");
//            sError += sKey_;
//            sError += "\".\n";
//            sError += currentFile();
//            sError += ".\n";
//            throw exception(sError.toStdString().c_str());
//        }
//        return;
//}


bool CSpreadsheet::addColumnVector(int nCol_,QString& sName_, const CMatrix<double>& mM_ )
{
    setFormula(0,nCol_,sName_);
    for (int i = 0; i < mM_.Len(); ++i) {
        setFormula(i+1,nCol_,QString("%1").arg(mM_(i)));
    }
    return true;
}
bool CSpreadsheet::addColumnVector(int nCol_,QString& sName_, const vector<double>& vM_ )
{
    setFormula(0,nCol_,sName_);
    for (unsigned int i = 0; i < vM_.size(); ++i) {
        setFormula(i+1,nCol_,QString("%1").arg(vM_[i]));
    }
    return true;
}

bool CSpreadsheet::addMatrix(int nRow_,int nCol_,QString& sName_, const CMatrix<double>& mM_ )
{
    setFormula(nRow_,nCol_,sName_);
    setFormula(nRow_,nCol_+1,QString("%1").arg(mM_.Rows()));
    setFormula(nRow_,nCol_+2,QString("%1").arg(mM_.Cols()));
    for (int r= 0; r < mM_.Rows(); ++r) 
    for (int c= 0; c < mM_.Cols(); ++c)
    {
        setFormula(nRow_+1+r,nCol_+c,QString("%1").arg(mM_(r,c)));
    }
    return true;
}

void CSpreadsheet::sortBySelectedColumn()
{
    if(Qt::AscendingOrder==_eSortOrder)
        _eSortOrder = Qt::DescendingOrder;
    else
        _eSortOrder = Qt::AscendingOrder;
    sortByColumn(currentColumn(),_eSortOrder);
}
void CSpreadsheet::sort(const CSpreadsheetCompare &compare)
{
    QList<QStringList> rows;
    QTableWidgetSelectionRange range = selectedRange();
    int i;

    for (i = 0; i < range.rowCount(); ++i) {
        QStringList row;
        for (int j = 0; j < range.columnCount(); ++j)
            row.append(formula(range.topRow() + i,range.leftColumn() + j));
        rows.append(row);
    }

    qStableSort(rows.begin(), rows.end(), compare);

    for (i = 0; i < range.rowCount(); ++i) {
        for (int j = 0; j < range.columnCount(); ++j)
            setFormula(range.topRow() + i, range.leftColumn() + j,
            rows[i][j]);
    }

    clearSelection();
    somethingChanged();
}
void CSpreadsheet::switchRows(int nRow1_, int nRow2_)
{
    for(int c=0;c<ColumnCount;c++)
    {
        QString sTemp = formula(nRow1_,c);
        setFormula(nRow1_,c,formula(nRow2_,c));
        setFormula(nRow2_,c,sTemp);
    }
}


void CSpreadsheet::searchMatrix( const QString& sKey_,CMatrix<double>* pMat_ )
{
    Q_ASSERT(pMat_);
    for(int r=0;r<RowCount;r++)
        for(int c=0;c<ColumnCount;c++){
            if(cell(r,c)&&cell(r,c)->text().contains(sKey_)&&cell(r,c+1)&&cell(r,c+2)){
                int nRow = cell(r,c+1)->formula().toInt();
                int nCol = cell(r,c+2)->formula().toInt();
                pMat_->SetSize(nRow,nCol,0);
                for(int i =0; i<nRow;i++)
                    for(int j =0; j<nCol;j++)
                    {
                        if(!cell(r+1+i,c+j)) 
                        {
                            QString sError("the entry of the matrix \"");
                            sError += sKey_;
                            sError += "\"";
                            sError += " should not be empty. \n";
                            sError += "In file ";
                            sError += currentFile();
                            sError += ".\n";
                            throw exception(sError.toStdString().c_str());
                        }
                        (*pMat_)(i,j)=cell(r+1+i,c+j)->formula().toDouble();
                    }
                    return;
            }  
        }

        {
            QString sError("you need to specify ");
            sError += sKey_;
            sError += ".\n";
            throw exception(sError.toStdString().c_str());
        }
        return;
}

void CSpreadsheet::searchColumnString( const QString& sKey_,vector<std::string>* pMat_ )
{
    Q_ASSERT(pMat_);
    for(int r=0;r<RowCount;r++)
        for(int c=0;c<ColumnCount;c++){
            if(cell(r,c)&&cell(r,c)->text().contains(sKey_)/*&&cell(r,c+1)&&cell(r,c+2)*/){
                (*pMat_).clear();
                for(int i =0; i<RowCount;i++)
                {
                    if(cell(r+1+i,c)) 
                        (*pMat_).push_back(cell(r+1+i,c)->formula().toStdString());
                    else
                        break;
                }
                return;
            }  
        }

        {
            QString sError("you need to specify ");
            sError += sKey_;
            sError += ".\n";
            throw exception(sError.toStdString().c_str());
        }
        return;
}

void CSpreadsheet::searchColumnInt( const QString& sKey_,vector<int>* pMat_ )
{
    Q_ASSERT(pMat_);
    for(int r=0;r<RowCount;r++)
        for(int c=0;c<ColumnCount;c++){
            if(cell(r,c)&&cell(r,c)->text().contains(sKey_)/*&&cell(r,c+1)&&cell(r,c+2)*/){
                (*pMat_).clear();
                for(int i =0; i<RowCount;i++)
                {
                    if(cell(r+1+i,c)) 
                        (*pMat_).push_back(cell(r+1+i,c)->formula().toInt());
                    else
                        break;
                }
                return;
            }  
        }

        {
            QString sError("you need to specify ");
            sError += sKey_;
            sError += ".\n";
            throw exception(sError.toStdString().c_str());
        }
        return;
}